---摘自能力勋章
-------------------------------------------------------------------------------------------------------------------------------------工具函数-------------------------------------------------------------------------------------------------------------------------------------
local uiloot={}--UI列表，方便重置

--拖拽坐标，局部变量存储，减少io操作
local dragpos={}

-- 函数名：loadDragPos
-- 作用：从本地读取之前保存的坐标数据，用于将背包恢复到上一次用户拖拽的位置
-- 参数：无
-- 返回值：无
-- 实现流程：异步读取本地存储文件 -> 数据解析 -> 更新内存缓存
local function loadDragPos()
    -- 异步获取持久化字符串数据，文件标识为"medal_drag_pos"
    TheSim:GetPersistentString("medal_drag_pos", function(load_success, data)
        -- 检查读取是否成功且数据不为空
        if load_success and data ~= nil then
            -- 在沙盒环境中安全执行数据字符串，将字符串转换回Lua表
            -- RunInSandbox确保执行安全，防止恶意代码注入
            local success, allpos = RunInSandbox(data)
            
            -- 检查数据解析是否成功且存在有效数据
            if success and allpos then
                -- 遍历所有保存的坐标数据
                for k, v in pairs(allpos) do
                    -- 只有当前内存中没有该类型的坐标数据时才加载
                    -- 这样可以避免覆盖已经存在的数据
                    if dragpos[k]==nil then
                        -- 将坐标数据转换为Vector3对象存储
                        -- 使用 or 0 确保坐标值的安全性，防止nil值
                        dragpos[k]=Vector3(v.x or 0, v.y or 0, v.z or 0)
                    end
                end
            end
        end
    end)
end



-- 函数名：saveDragPos
-- 作用：将当前的拖拽坐标数据保存到本地
-- 参数：
--   dragtype: string类型，拖拽类型标识，可选参数，当前版本中未使用
--   pos: Vector3类型，坐标位置，可选参数
-- 返回值：无
-- 实现流程：检查数据 -> 序列化 -> 写入持久化存储
local function saveDragPos(dragtype,pos)
    -- 检查dragpos表中是否有数据需要保存
    -- next()函数用于检查表是否为空，比#操作符更可靠
    if next(dragpos) then
        -- 使用DataDumper将Lua表序列化为字符串
        -- 第二个参数nil表示不限制层级，第三个参数true表示紧凑格式
        local str = DataDumper(dragpos, nil, true)
        
        -- 将序列化后的字符串保存到持久化存储
        -- 第三个参数false表示不加密存储
        TheSim:SetPersistentString("medal_drag_pos", str, false)
    end
end


--获取拖拽坐标
local function GetMedalDragPos(dragtype)
	if dragpos[dragtype]==nil then
		loadDragPos()
	end
	return dragpos[dragtype]
end





--设置UI可拖拽(self,拖拽目标,拖拽标签,拖拽信息)
local function MakeMedalDragableUI(self,dragtarget,dragtype,dragdata)
	self.candrag=true--可拖拽标识(防止重复添加拖拽功能)
	uiloot[self]=self:GetPosition()--存储UI默认坐标
	--给拖拽目标添加拖拽提示
	if dragtarget then
		--dragtarget:SetTooltip(STRINGS.MEDAL_UI.DRAGABLETIPS)
		local oldOnControl=dragtarget.OnControl
		dragtarget.OnControl = function (self,control, down, ...)
			local parentwidget=self:GetParent()--控制父体坐标,让格子跟随父体移动
			--按下右键可拖动
			if parentwidget and parentwidget.Passive_OnControl then
				parentwidget:Passive_OnControl(control, down)
			end

			if oldOnControl then
				return oldOnControl(self,control,down, ...)
			end
		end
	end
	
	--被控制(控制状态，是否按下)，CONTROL_SECONDARY是鼠标右键常量
	function self:Passive_OnControl(control, down)
		if self.focus and control == CONTROL_SECONDARY then
			if down then
				self:StartDrag()
			else
				self:EndDrag()
			end
		end
	end
	--设置拖拽坐标
	function self:SetDragPosition(x, y, z)
		local pos
		if type(x) == "number" then
			pos = Vector3(x, y, z)
		else
			pos = x
		end
		
		local self_scale=self:GetScale()
		local offset=dragdata and dragdata.drag_offset or 1--偏移修正(容器是0.6)
		local newpos=self.p_startpos+(pos-self.m_startpos)/(self_scale.x/offset)--修正偏移值
		self:SetPosition(newpos)--设定新坐标
	end
	
	--开始拖动
	function self:StartDrag()
		if not self.followhandler then
			local mousepos = TheInput:GetScreenPosition()
			self.m_startpos = mousepos--鼠标初始坐标
			self.p_startpos = self:GetPosition()--面板初始坐标
			self.followhandler = TheInput:AddMoveHandler(function(x,y)
				self:SetDragPosition(x,y,0)
				if not Input:IsMouseDown(MOUSEBUTTON_RIGHT) then
					self:EndDrag()
				end
			end)
			self:SetDragPosition(mousepos)
		end
	end
	
	--停止拖动
	function self:EndDrag()
		if self.followhandler then
			self.followhandler:Remove()
		end
		self.followhandler = nil
		self.m_startpos = nil
		self.p_startpos = nil
		local newpos=self:GetPosition()
		if dragtype then
			dragpos[dragtype]=newpos--记录记录拖拽后坐标
		end
		saveDragPos()--存储坐标
	end
end

--重置拖拽坐标
function ResetMedalUIPos()
	dragpos={}
	TheSim:SetPersistentString("medal_drag_pos", "", false)
	for k, v in pairs(uiloot) do
		if k.inst and k.inst:IsValid() then
			k:SetPosition(v)--重置坐标
		else
			uiloot[k]=nil--失效了的就清掉吧
		end
	end
end









-------------------------------------------------------------------------------------------------------------------------------------主函数-------------------------------------------------------------------------------------------------------------------------------------
--hook容器组件，目前是用于拖拽容器
AddClassPostConstruct("widgets/containerwidget", function(self)
    local oldOpen = self.Open
    self.Open = function(self, container, doer, ...)
        oldOpen(self, container, doer, ...)
        -- 给容器添加拖拽功能
        if  self.container and self.container.replica.container then
            local widget = self.container.replica.container:GetWidget()
            if widget then    
                -- 拖拽坐标标签，用容器名
                local dragname= self.container and self.container.prefab

                if dragname then
                    -- 设置可拖拽
                    if not self.candrag then
                        MakeMedalDragableUI(self,self.bgimage,dragname,{drag_offset=0.6})
                        MakeMedalDragableUI(self,self.bganim,dragname,{drag_offset=0.6})
                    end
                    -- 设置容器坐标
                    local newpos=GetMedalDragPos(dragname)
                    if newpos then
                        if self.container:HasTag("_equippable") and not self.container.isopended then
                            self.container:DoTaskInTime(0, function()
                                self:SetPosition(newpos)
                            end)
                            self.container.isopended=true
                        else
                            self:SetPosition(newpos)
                        end
                    end
                end
            end
        end
    end
end)







